﻿using System;
using System.Collections.Generic;
using System.Web;
using umbraco.interfaces;
using umbraco.BusinessLogic;
using umbraco.cms.businesslogic.web;
using Nibble.Umb.Locator.GeoCoding.Services;
using Nibble.Umb.Locator.GeoCoding;
using Nibble.Umb.Locator.GeoCoding.Services.Google;
using System.Xml;

namespace Nibble.Umb.Locator.EventHandlers
{
    /// <summary>
    /// auto geocode event handler, this will fetch the coordinates based on an 
    /// address/postcode found in the properties of a document and store them
    /// </summary>
    public class AutoGeoCode : ApplicationBase
    {
        public AutoGeoCode()
        {
            if (AutoGeoCodeEnabled())
            {
                Document.AfterSave += new Document.SaveEventHandler(Document_AfterSave);
            }
        }

        /// <summary>
        /// Event handler that fires after a document has been saved 
        /// It will set the latitude/longitude based on an address/postcode
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="umbraco.cms.businesslogic.SaveEventArgs"/> instance containing the event data.</param>
        void Document_AfterSave(Document sender, umbraco.cms.businesslogic.SaveEventArgs e)
        {
            if (IsAllowedDocumentType(sender.ContentType.Alias))
            {
                string address = string.Empty;

                foreach (string addressAlias in GetAutoGeoCodeConfig("autoGeoCodeAddressAliases").Split(';'))
                {
                    address += sender.getProperty(addressAlias).Value.ToString() + ", ";
                }
                
                address = address.Substring(0, address.Length > 0 ? address.Length - 2 : 0);


                IGeoCoder geoCoder = new GoogleGeoCoder(Utility.GetGoogleMapsKey());
                Address[] addresses = geoCoder.GeoCode(address);

                if (addresses.Length == 1)
                {
                    sender.getProperty(GetAutoGeoCodeConfig("autoGeoCodeLocationAlias")).Value = 
                        addresses[0].Coordinates.Latitude.ToString(Utility.NumberFormatInfo) +
                        "," + addresses[0].Coordinates.Longitude.ToString(Utility.NumberFormatInfo);
                }
            }
        }

        /// <summary>
        /// Determines whether auto geocode eventhandler is enabled.
        /// </summary>
        /// <returns></returns>
        private bool AutoGeoCodeEnabled()
        {
            try
            {
                XmlDocument config = new XmlDocument();
                config.Load(HttpContext.Current.Server.MapPath("/config/Nibble.Umb.Locator.config"));

                XmlNode key = config.SelectSingleNode("/config");

                return key.Attributes["autoGeoCodeEnabled"].Value == "1";
            }
            catch
            {
                return false;
            }
        }

        /// <summary>
        /// Determines whether  the alias is an allowed document type for the auto geocode eventhandler
        /// </summary>
        /// <param name="alias">The alias.</param>
        /// <returns>
        /// 	<c>true</c> if [is allowed document type] [the specified alias]; otherwise, <c>false</c>.
        /// </returns>
        private bool IsAllowedDocumentType(string alias)
        {
            try
            {
                foreach (string docTypeAlias in GetAutoGeoCodeConfig("autoGeoCodeDocumentTypeAliases").Split(';'))
                {
                    if (docTypeAlias == alias)
                    {
                        return true;
                    }
                }
                return false;
            }
            catch
            {
                return false;
            }
        }

        /// <summary>
        /// Gets an auto geocode config setting.
        /// </summary>
        /// <param name="item">The item.</param>
        /// <returns></returns>
        private string GetAutoGeoCodeConfig(string item)
        {
            try
            {
                XmlDocument config = new XmlDocument();
                config.Load(HttpContext.Current.Server.MapPath("/config/Nibble.Umb.Locator.config"));

                XmlNode key = config.SelectSingleNode("/config");

                return key.Attributes[item].Value;
            }
            catch
            {
                return string.Empty;
            }
        }
    }
}
